/*
* @desc:阿里云短信发送
* @company:云南奇讯科技有限公司
* @Author: yixiaohu
* @Date:   2022/1/12 11:58
 */

package service

import (
	"context"
	"fmt"
	openapi "github.com/alibabacloud-go/darabonba-openapi/client"
	dysmsapi20170525 "github.com/alibabacloud-go/dysmsapi-20170525/v2/client"
	"github.com/alibabacloud-go/tea/tea"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/text/gregex"
	"github.com/gogf/gf/v2/util/gconv"
	"github.com/tiger1103/gfast/v3/internal/app/plugins/sms/dao"
	"github.com/tiger1103/gfast/v3/internal/app/plugins/sms/driver"
	"github.com/tiger1103/gfast/v3/internal/app/plugins/sms/model"
)

var Aly = new(alyService)

type alyConfig struct {
	AccessKeyId     string
	AccessKeySecret string
	Host            string
	TemplateCode    g.Map
	SignName        g.Map
}

type alyService struct {
	AlyConfig *alyConfig
}

func (s *alyService) SendTemplateSms(args *driver.SendSmsArgs) (err error) {
	err = s.setConfig(args.Ctx)
	if err != nil {
		return
	}
	client, err := s.createClient()
	if err != nil {
		return
	}
	if len(args.Mobiles) == 0 {
		err = gerror.New("手机号不能为空")
		return
	}
	if len(args.Params) == 0 {
		err = gerror.New("参数不能为空")
		return
	}
	var templateId string
	if v, ok := s.AlyConfig.TemplateCode["notice"]; ok {
		templateId = gconv.String(v)
	}
	if args.TemplateId != "" {
		templateId = args.TemplateId
	}
	signNameJson := make([]string, len(args.Mobiles))
	templateParamJson := make([]map[string]string, len(args.Mobiles))
	for i, mobile := range args.Mobiles {
		// 清除手机号中的空格和横杆
		args.Mobiles[i], err = gregex.ReplaceString("\\s|-", "", mobile)
		if err != nil {
			return
		}
		signNameJson[i] = gconv.String(s.AlyConfig.SignName["notice"])
		templateParamJson[i] = map[string]string{"name": args.Params[0]}
	}
	sendBatchSmsRequest := &dysmsapi20170525.SendBatchSmsRequest{
		PhoneNumberJson:   tea.String(gconv.String(args.Mobiles)),
		SignNameJson:      tea.String(gconv.String(signNameJson)),
		TemplateCode:      tea.String(templateId),
		TemplateParamJson: tea.String(gconv.String(templateParamJson)),
	}
	// 复制代码运行请自行打印 API 的返回值
	var result *dysmsapi20170525.SendBatchSmsResponse
	result, err = client.SendBatchSms(sendBatchSmsRequest)
	//g.Log().Debug(result)
	if err != nil {
		return
	}
	//写入发送日志
	if err = Sms.WriteLog(args.Ctx, &model.ClientArg{
		SmsType:    "aly",
		MsgType:    "SendTemplateSms",
		Result:     gconv.String(result.Body),
		TemplateId: gconv.String(s.AlyConfig.TemplateCode["notice"]),
		Mobiles:    args.Mobiles,
		Params:     args.Params,
	}); err != nil {
		g.Log().Error(args.Ctx, err)
	}
	return
}

func (s *alyService) SendVerifyCode(args *driver.SendSmsArgs) (err error) {
	err = s.setConfig(args.Ctx)
	if err != nil {
		return
	}
	if len(args.Mobiles) < 1 {
		err = gerror.New("手机号码不能为空")
		return
	}
	mobile, _ := gregex.ReplaceString("\\s|-", "", args.Mobiles[0])
	authCode, err := Sms.CreateVerifyCode(args.Ctx, mobile)
	if err != nil {
		return
	}
	client, err := s.createClient()
	if err != nil {
		return
	}
	sendBatchSmsRequest := &dysmsapi20170525.SendSmsRequest{
		PhoneNumbers:  tea.String(mobile),
		SignName:      tea.String(gconv.String(s.AlyConfig.SignName["verifyCode"])),
		TemplateCode:  tea.String(gconv.String(s.AlyConfig.TemplateCode["verifyCode"])),
		TemplateParam: tea.String(fmt.Sprintf(`{"code":"%d"}`, authCode)),
	}
	// 复制代码运行请自行打印 API 的返回值
	var result *dysmsapi20170525.SendSmsResponse
	result, err = client.SendSms(sendBatchSmsRequest)
	//g.Log().Debug(result)
	if err != nil {
		return
	}
	// 写入发送日志
	if err = Sms.WriteLog(args.Ctx, &model.ClientArg{
		SmsType:    "aly",
		MsgType:    "SendVerifyCode",
		Result:     gconv.String(result.Body),
		TemplateId: gconv.String(s.AlyConfig.TemplateCode["verifyCode"]),
		Mobiles:    args.Mobiles,
		Params:     []string{gconv.String(authCode)},
	}); err != nil {
		g.Log().Error(args.Ctx, err)
	}
	return
}

func (s *alyService) CheckVerifyCode(ctx context.Context, mobile string, code string) error {
	// 本地服务器check
	return Sms.CheckVerifyCode(ctx, mobile, code)
}

// 设置配置
func (s *alyService) setConfig(ctx context.Context) (err error) {
	if s.AlyConfig == nil {
		s.AlyConfig, err = s.GetConfig(ctx)
	}
	return
}

func (s *alyService) GetConfig(ctx context.Context) (config *alyConfig, err error) {
	smsConfig, err := dao.PluginSmsConfig.Ctx(ctx).Where("sms_type", "aly").One()
	if err != nil {
		g.Log().Error(ctx, err)
		return
	}
	if smsConfig.IsEmpty() {
		err = gerror.New("短信配置信息不存在")
		g.Log().Error(ctx, err)
		return
	}

	if v, ok := smsConfig["config"]; ok {
		err = gconv.Struct(v, &config)
		if err != nil {
			g.Log().Error(ctx, err)
			return
		}
	}
	if config.AccessKeyId == "" || config.AccessKeySecret == "" {
		err = gerror.New("阿里云短信配置有错误")
		g.Log().Error(ctx, err)
		return
	}
	return
}

/**
 * 使用AK&SK初始化账号Client
 * @param accessKeyId
 * @param accessKeySecret
 * @return Client
 * @throws Exception
 */
func (s *alyService) createClient() (_result *dysmsapi20170525.Client, _err error) {
	config := &openapi.Config{
		// 您的AccessKey ID
		AccessKeyId: tea.String(s.AlyConfig.AccessKeyId),
		// 您的AccessKey Secret
		AccessKeySecret: tea.String(s.AlyConfig.AccessKeySecret),
	}
	// 访问的域名
	config.Endpoint = tea.String(s.AlyConfig.Host)
	_result = &dysmsapi20170525.Client{}
	_result, _err = dysmsapi20170525.NewClient(config)
	return _result, _err

}
